package com.imagination.applet.domain.fsImage.service.impl;

import com.imagination.applet.domain.adapter.OSSConfiguration;
import com.imagination.applet.domain.aiimage.model.AIImage;
import com.imagination.applet.domain.aiimage.service.AIImageQueryService;
import com.imagination.applet.domain.fsImage.model.FaceSwapImage;
import com.imagination.applet.domain.fsImage.repository.FaceSwapImageRepository;
import com.imagination.applet.domain.fsImage.service.FaceSwapImageCommandService;
import com.imagination.applet.domain.fsImage.service.FaceSwapImageQueryService;
import com.imagination.applet.domain.photo.model.UserPhoto;
import com.imagination.applet.domain.photo.service.UserPhotoQueryService;
import com.imagination.applet.domain.utils.ImagePathGenerator;
import com.imagination.applet.infrastructure.process.PythonCommand;
import com.imagination.applet.infrastructure.utils.DateTimeUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor(onConstructor = @__({@Autowired}))
public class FaceSwapImageServiceImpl implements FaceSwapImageQueryService, FaceSwapImageCommandService, InitializingBean {

    private final UserPhotoQueryService userPhotoQueryService;
    private final AIImageQueryService AIImageQueryService;

    private final FaceSwapImageRepository faceChangingImageRepository;

    private String[] commandTemplate;

    @Value("${roop.commands.run}")
    private String runCommand;

    @Override
    public FaceSwapImage applyFaceChanging(Long userId, Long photoId, Long generatedImageId) {
        UserPhoto photo = userPhotoQueryService.queryUserPhoto(userId, photoId);
        AIImage image = AIImageQueryService.queryGeneratedImage(generatedImageId);

        String filePath = ImagePathGenerator.nextPathWithSuffix("jpeg");
        String[] commands = buildRoopCommand(photo, image, filePath);
        try {
            PythonCommand.getInstance().runAndWait(commands);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return save(userId, photo, image, filePath);
    }

//    @Override
//    @Transactional
//    public int removeFaceChangingImage(Long imageId, Long userId) {
//        FaceSwapImage image = faceChangingImageRepository.getReferenceById(imageId);
//        if(!userId.equals(image.getUserId())){
//            throw new RuntimeException();
//        }
//        return faceChangingImageRepository.deletedById(imageId);
//    }

    @Override
    public List<FaceSwapImage> queryFaceChangingImagesByPageable(Long userId, Pageable pageable) {
        return null;
    }

    private String[] buildRoopCommand(UserPhoto photo, AIImage image, String outputPath) {
        String[] commands = commandTemplate.clone();
        commands[3] = photo.getPath();
        commands[5] = image.getPath();
        commands[7] = OSSConfiguration.path + FaceSwapImage.PREFIX_PATH + outputPath;
        return commands;
    }

    private FaceSwapImage save(Long userId, UserPhoto photo, AIImage image, String filePath) {
        FaceSwapImage entity = FaceSwapImage.builder()
                .userId(userId)
                .photoId(photo.getId())
                .aiImageId(image.getId())
                .serialNo(DateTimeUtils.currentString())
                .imagePath(filePath)
                .build();
        return faceChangingImageRepository.save(entity);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        commandTemplate = new String[12];
        commandTemplate[0] = "python3.10";
        commandTemplate[1] = runCommand;
        commandTemplate[2] = "--source";
        commandTemplate[3] = "***";
        commandTemplate[4] = "--target";
        commandTemplate[5] = "***";
        commandTemplate[6] = "--output";
        commandTemplate[7] = "***";
        commandTemplate[8] = "--frame-processor";
        commandTemplate[9] = "face_swapper";
        commandTemplate[10] = "face_enhancer";
        commandTemplate[11] = "--keep-fps";
    }
}
